package com.franklin.java.completion.method.param;

import com.franklin.java.api.psi.data.PsiData;
import com.franklin.java.api.psi.data.resolver.PsiDataResolverFactory;
import com.franklin.java.completion.AbstractJavaDataCompletionContributor;
import com.franklin.java.completion.CompletionOrder;
import com.franklin.java.completion.MyInsertHandler;
import com.franklin.java.configuration.sql.completion.TableNamePrefixState;
import com.franklin.java.entity.sql.ColumnInfo;
import com.franklin.java.service.database.DataSourceServiceSupport;
import com.franklin.java.service.database.DatabaseHandler;
import com.franklin.java.utils.CompletionUtils;
import com.franklin.java.utils.EntityClassHelper;
import com.franklin.java.utils.PsiUtils;
import com.franklin.plugins.common.collection.PrettyArrayList;
import com.franklin.plugins.common.collection.PrettyHashSet;
import com.franklin.plugins.common.utils.DataCheckUtils;
import com.franklin.plugins.common.utils.StringHelper;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
 * Mybatis-Plus Wrapper对象字符串代码提示
 *
 * @author Franklin
 * @since 2021/9/9 16:57
 */
public class MybatisPlusWrapperCompletionContributor extends AbstractJavaDataCompletionContributor {

    @Override
    public boolean isCorrectCompletionParameter(@NotNull CompletionParameters parameters) {
        return super.isCorrectCompletionParameter(parameters);
    }

    @Override
    public List<LookupElement> getLookupElements(CompletionParameters parameters) {

        PsiFile psiFile = parameters.getOriginalFile();
        PsiElement psiElement = psiFile.findElementAt(parameters.getOffset());
        if (Objects.isNull(psiElement)) {
            return Collections.emptyList();
        }

        //方法调用链
        PsiMethodCallExpression fullMethodCallExpression = PsiUtils.findFullMethodCallExpression(psiElement);
        if (Objects.isNull(fullMethodCallExpression)) {
            return Collections.emptyList();
        }
        PsiElement wrapperElement = fullMethodCallExpression.findElementAt(0);
        if (Objects.isNull(wrapperElement)) {
            return Collections.emptyList();
        }
        String wrapperName = wrapperElement.getText();
        PsiData psiData = PsiDataResolverFactory.resolveData(wrapperName, wrapperName, wrapperElement);
        String typeFullName = psiData.getTypeFullName();
        if (!isMpWrapper(typeFullName)) {
            return Collections.emptyList();
        }
        //解析泛型
        String type = psiData.getType();
        String entityName = PsiUtils.resolveGenericType(type);
        Project project = wrapperElement.getProject();
        PsiClass entityClass = PsiUtils.findClassBySimpleName(
            project,
            wrapperElement.getContainingFile().getVirtualFile().getPath(),
            entityName
        );
        if (Objects.isNull(entityClass)) {
            return Collections.emptyList();
        }

        String tableName = EntityClassHelper.resolveTableName(entityClass);
        if (DataCheckUtils.isEmpty(tableName)) {
            return Collections.emptyList();
        }
        Set<String> tableNames = new PrettyHashSet<>();
        tableNames.add(tableName);
        if (tableName.equals(StringHelper.getTableName(entityName))) {
            String[] prefixes = TableNamePrefixState.getPrefix(project).split(";");
            for (String prefix : prefixes) {
                tableNames.add(prefix + "_" + tableName);
            }
        }
        DatabaseHandler databaseHandler = DataSourceServiceSupport.getInstance().getDatabaseHandler(wrapperElement);
        Map<String, List<ColumnInfo>> columns = databaseHandler.getColumns(tableNames);
        if (DataCheckUtils.isEmpty(columns)) {
            return Collections.emptyList();
        }

        String text = fullMethodCallExpression.getMethodExpression().getText();
        boolean isSelectMethod = false;
        if (text.endsWith("select")) {
            isSelectMethod = true;
        }

        List<LookupElement> result = new PrettyArrayList<>();
        boolean finalIsSelectMethod = isSelectMethod;
        tableNames.forEach(name -> {
            List<ColumnInfo> columnInfoList = columns.getOrDefault(name, Collections.emptyList());
            columnInfoList.forEach(columnInfo -> {
                LookupElement lookupElement = CompletionUtils.getLookElement(
                    '"' + columnInfo.getColumnName() + '"',
                    "String",
                    "  " + columnInfo.getComment(),
                    new MyInsertHandler()
                );
                result.add(lookupElement);

                if (finalIsSelectMethod && columnInfo.getColumnName().equals("id")) {
                    String aliasId = "id As " + StringHelper.firstToLowerCase(entityName) + "Id";
                    LookupElement idElement = CompletionUtils.getLookElement(
                        '"' + aliasId + '"',
                        "String",
                        "  " + columnInfo.getComment(),
                        new MyInsertHandler()
                    );
                    result.add(idElement);
                }
            });
        });
        return result;
    }

    /**
     * 判断是否是Wrapper对象<br>
     *
     * @param typeFullName:
     * @return boolean
     * @author Franklin
     * @since 2021/9/9 17:23
     */
    private boolean isMpWrapper(String typeFullName) {
        return typeFullName.contains("com.baomidou.mybatisplus.core.conditions") && typeFullName.contains("Wrapper");
    }

    @Override
    public CompletionOrder getOrder() {
        return CompletionOrder.HIGH;
    }
}
